import java.util.ArrayList;
import javax.swing.SwingUtilities;

/**
 * Utility class used for image preprocessing
 *
 */
public final class ImageComputingHelper {

	/**
	 * Return an array containing the color value of every pixel around the pixel in (x,y). <br>
	 * Value are sent in this order : <br>
	 * 8 1 2 <br>
	 * 7 X 3 <br>
	 * 6 5 4 <br> 
	 * If the value does not exist ( because it's out of the picture ), null is put at this value position
	 * @param x X position of the center pixel
	 * @param y Y position of the center pixel
	 * @param i The image 
	 * @return An array containing the surrounding pixels
	 */
	public static ArrayList<Pixel> getSurroundingPixel( int x, int y, Image i) {
		ArrayList<Pixel> surrounding = new ArrayList<Pixel>();
		int matrix[][] = i.getMatrix();
		// upper 
		if (y > 0) {
			surrounding.add(new Pixel(x, y-1, matrix[x][y-1]));
		}
		else {
			surrounding.add(null);
		}
		// upper right
		if (y > 0 && x < (Image.IMAGE_WIDTH - 1)) {
			surrounding.add(new Pixel(x+1, y-1, matrix[x+1][y-1]));
		}
		else {
			surrounding.add(null);
		}
		// right
		if (x < (Image.IMAGE_WIDTH - 1)) {
			surrounding.add(new Pixel(x+1, y, matrix[x+1][y]));
		}
		else {
			surrounding.add(null);
		}
		// lower right
		if (x < (Image.IMAGE_WIDTH -1) && y < (Image.IMAGE_HEIGHT -1)) {
			surrounding.add(new Pixel(x+1, y+1, matrix[x+1][y+1]));
		}
		else {
			surrounding.add(null);
		}
		// lower
		if (y < (Image.IMAGE_HEIGHT -1)) {
			surrounding.add(new Pixel(x, y+1, matrix[x][y+1]));
		}
		else {
			surrounding.add(null);
		}
		// lower left
		if (y < (Image.IMAGE_HEIGHT -1) && x > 0) {
			surrounding.add(new Pixel(x-1, y+1, matrix[x-1][y+1]));
		}
		else {
			surrounding.add(null);
		}
		// left
		if (x > 0) {
			surrounding.add(new Pixel(x-1, y, matrix[x-1][y]));
		}
		else {
			surrounding.add(null);
		}
		// upper left
		if (x > 0 && y > 0) {
			surrounding.add(new Pixel(x-1, y-1, matrix[x-1][y-1]));
		}
		else {
			surrounding.add(null);
		}
		return surrounding;
	}

	/**
	 * Remove noise in the image
	 * @param img the image to "denoise"
	 * @return The new matrix for the image
	 */
	public static int[][] removeLonelyPixels(Image img) {
		int newMatrix[][] = new int[Image.IMAGE_WIDTH][Image.IMAGE_HEIGHT];
		for (int i = 0; i < Image.IMAGE_WIDTH; i++) {
			for (int j = 0; j < Image.IMAGE_HEIGHT; j++) {
				ArrayList<Pixel> surroundings = getSurroundingPixel(i, j, img);
				int count = 0;
				for (Pixel pixel : surroundings) {
					if (pixel != null && pixel.getColor() != Image.WHITE) {
						count++;
					}
				}
				newMatrix[i][j] = count <= 4? Image.WHITE : img.getPixelValue(i, j);
			}
		}
		return newMatrix;
	}

	public static int getMediumPixelValue(Image img) {
		int somme = 0;
		for (int i =0; i< Image.IMAGE_WIDTH; i++) {
			for (int j = 0; j < Image.IMAGE_HEIGHT; j++) {
				somme+= img.getPixelValue(i, j);
			}
		}
		return somme / ( Image.IMAGE_HEIGHT * Image.IMAGE_WIDTH);
	}

	public static void applyThreshold(int treshold, Image img) {
		int newMatrix[][] = new int[Image.IMAGE_WIDTH][Image.IMAGE_HEIGHT];
		for (int i =0; i< Image.IMAGE_WIDTH; i++) {
			for (int j = 0; j < Image.IMAGE_HEIGHT; j++) {
				if (img.getPixelValue(i, j) < treshold) {
					newMatrix[i][j] = Image.WHITE;
				}
				else {
					newMatrix[i][j] = Image.BLACK;
				}
			}
		}
		img.setMatrix(newMatrix);
	}
	

	public static void showImage(final Image i) {
		SwingUtilities.invokeLater(new Runnable(){
			public void run(){
				// New JDialog
				ImageViewer window = new ImageViewer(i.getMatrix(), i.getName());
				window.setVisible(true); // Make it visible
				window.repaint();
			}
		});
	}
	
	public static void preProcessImages(ArrayList<Image> imageList) {
		for (Image img : imageList) {
			img.turnImage();
			img.setMatrix(removeLonelyPixels(img));
		}
	}
}
